package com.newcoder.service.impl;


import com.newcoder.entity.Comment;
import com.newcoder.entity.DiscussPost;
import com.newcoder.entity.Event;
import com.newcoder.event.EventProducer;
import com.newcoder.mapper.CommentMapper;
import com.newcoder.mapper.DiscussPostMapper;
import com.newcoder.service.CommentService;
import com.newcoder.util.HostHolder;
import com.newcoder.util.RedisKeyUtil;
import com.newcoder.util.ResponseWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.HtmlUtils;

import java.util.Date;
import java.util.List;

import static com.newcoder.util.CommunityConstant.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author yjh
 * @since 2024-12-04 10:03:25
 */
@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    CommentMapper commentMapper;

    @Autowired
    private HostHolder hostHolder;

    @Autowired
    private DiscussPostMapper discussPostMapper;

    @Autowired
    private EventProducer eventProducer;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public ResponseWrapper insertComment(Integer discussPostId, Comment comment) {
        if (comment == null) {
            return ResponseWrapper.parameterError("评论不能为空！");
        }
        //输入内容检查，判断是否包含html标签
        comment.setContent(HtmlUtils.htmlEscape(comment.getContent()));
        comment.setStatus(0);
        comment.setCreateTime(new Date());

        int i = commentMapper.insertComment(comment);
        if (i != 1) {
            return ResponseWrapper.parameterError("评论失败！");
        }

        // 触发评论事件
        Event event = new Event()
                .setTopic(TOPIC_COMMENT)
                .setUserId(hostHolder.getUser().getId())
                .setEntityType(comment.getEntityType())
                .setEntityId(comment.getEntityId())
                .setData("postId", discussPostId);
        if (comment.getEntityType() == ENTITY_TYPE_POST) {
            DiscussPost target = discussPostMapper.selectDiscussPostById(comment.getEntityId());
            event.setEntityUserId(target.getUserId());
        } else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) {
            Comment target = commentMapper.selectCommentById(comment.getEntityId());
            event.setEntityUserId(target.getUserId());
        }
        eventProducer.fireEvent(event);

        if (comment.getEntityType() == ENTITY_TYPE_POST) {
            // 触发发帖事件
            event = new Event()
                    .setTopic(TOPIC_PUBLISH)
                    .setUserId(comment.getUserId())
                    .setEntityType(ENTITY_TYPE_POST)
                    .setEntityId(discussPostId);
            eventProducer.fireEvent(event);
            // 计算帖子分数
            String redisKey = RedisKeyUtil.getPostScoreKey();
            redisTemplate.opsForSet().add(redisKey, discussPostId);
        }

        return ResponseWrapper.markCustom(true, 200,"评论成功！");
    }

    @Override
    public ResponseWrapper deleteCommentById(Integer id) {
        if (id == null) {
            return ResponseWrapper.parameterError("id不能为空！");
        }
        int i = commentMapper.deleteCommentById(id);
        if (i != 1) {
            return ResponseWrapper.parameterError("删除失败！");
        }
        return ResponseWrapper.markCustom(true, 200,"删除成功！");
    }

    @Override
    public ResponseWrapper selectCommentById(Integer id) {
        if (id == null) {
            return ResponseWrapper.parameterError("id不能为空！");
        }
        Comment comment = commentMapper.selectCommentById(id);
        if (comment == null) {
            return ResponseWrapper.parameterError("查找失败！");
        }
        ResponseWrapper wrapper = ResponseWrapper.markCustom(true, 200,"查找成功！");
        wrapper.getData().put("comment", comment);
        return wrapper;
    }

    //文章一级评论，评论文章的评论，无需分页，加载全部（前端可以使用懒加载）
    @Override
    public ResponseWrapper selectDiscussPostAllComments(Integer entityId) {
        if(entityId==null){
            return ResponseWrapper.parameterError("不能为空！");
        }
        Integer entityType = 1;
        //当前页第一个数据下标offset
        Integer currentNum = 0;
        Integer pageSize = Integer.MAX_VALUE;
        //所有数据的数量
        Integer total = commentMapper.selectCommentTotal(entityType, entityId);
        //当前页数据
        List<Comment> list = commentMapper.selectCommentsPage(entityType, entityId, currentNum, pageSize);

        ResponseWrapper wrapper = ResponseWrapper.markSuccess();
        wrapper.getData().put("commentList",list);               //当前页数据
        wrapper.getData().put("total", total);                  //总数据个数
        return wrapper;
    }

    //文章二级评论，评论用户评论的评论，分页
    @Override
    public ResponseWrapper selectCommentsPage(Integer entityId, Integer currentPage, Integer pageSize) {
        Integer entityType = 2;
        //当前页第一个数据下标offset
        Integer currentNum = (currentPage - 1) * pageSize;
        //所有数据的数量
        Integer total = commentMapper.selectCommentTotal(entityType, entityId);
        //当前页数据
        List<Comment> list = commentMapper.selectCommentsPage(entityType, entityId, currentNum, pageSize);

        Integer pages = total%pageSize == 0 ? total/pageSize : total/pageSize + 1;
        ResponseWrapper wrapper = ResponseWrapper.markSuccess();
        wrapper.getData().put("commentList",list);               //当前页数据
        wrapper.getData().put("total", total);                  //总数据个数
        wrapper.getData().put("currentPage", currentPage);      //当前页
        wrapper.getData().put("currentNum", currentNum);        //当前页第一个数据下标
        wrapper.getData().put("pageSize", pageSize);            //页大小
        wrapper.getData().put("pages", pages);                  //总页数
        return wrapper;
    }

}
